package local

import (
	"fmt"
	"github.com/spf13/cast"
	"github.com/thoas/go-funk"
	"github.com/xuri/excelize/v2"
	"log"
	"os"
	"xiuxian_help_tool/backend/app"
	"xiuxian_help_tool/backend/model/res"
)

type CardFileService struct{}

var (
	CardFileServiceApp = new(CardFileService)

	CacheCardFileTreeDataKeyPrefix = "card_file_tree:"

	CacheCardFileTreeDataKey = func(id int) string {
		return fmt.Sprintf("%s%d", CacheCardFileTreeDataKeyPrefix, id)
	}

	CacheCardFileAccountMapKeyPrefix = "card_file_account_map:"

	CacheCardFileAccountMapKey = func(id int) string {
		return fmt.Sprintf("%s%d", CacheCardFileAccountMapKeyPrefix, id)
	}

	CacheCardClassifyListKeyPrefix = "card_classify_list:"

	CacheCardClassifyListKey = func(id int) string {
		return fmt.Sprintf("%s%d", CacheCardClassifyListKeyPrefix, id)
	}
)

// GetCardInfoList 获取卡片文件列表
func (s *CardFileService) GetCardInfoList() (*[]res.CardFileInfoRes, error) {
	list, err := app.App().Storage().GetCardFileList()
	if err != nil {
		return nil, err
	}
	cardFileInfoResList := make([]res.CardFileInfoRes, 0)
	for _, info := range list {
		exist := false
		if funk.NotEmpty(info.FilePath) {
			exist = fileExists(info.FilePath)
			log.Println(info.FilePath, exist)
		}
		cardFileInfoRes := res.CardFileInfoRes{
			ID:       info.ID,
			FileName: info.FileName,
			FilePath: info.FilePath,
			Exist:    exist,
		}
		cardFileInfoResList = append(cardFileInfoResList, cardFileInfoRes)
	}
	return &cardFileInfoResList, nil
}

// AddCardFileInfo 添加卡片文件
func (s *CardFileService) AddCardFileInfo(path string) bool {
	app.App().Ctx()
	err := app.App().Storage().AddCardFile(path)
	if err != nil {
		return false
	}
	return true
}

// DeleteCardFileInfo 删除卡片文件
func (s *CardFileService) DeleteCardFileInfo(id int) bool {
	err := app.App().Storage().DeleteCardFile(id)
	if err != nil {
		return false
	}
	return true
}

// LoadCardFile 加载卡片文件
func (s *CardFileService) LoadCardFile(id int) (*[]res.TreeNode, error) {
	treeData, _, _ := ReadCardFileData(id)
	return &treeData, nil
}

func ReadCardFileData(fileId int) ([]res.TreeNode, map[int64]res.CardInfo, []res.BoxInfo) {
	file, err := app.App().Storage().FindCardFile(fileId)
	if err != nil {
		log.Fatal(err)
		return nil, nil, nil
	}
	// 声明并初始化 BoxInfo 切片
	var treeData []res.TreeNode
	var keyMaps map[int64]res.CardInfo
	var classifyList []res.BoxInfo
	var cacheTreeOk bool
	var cacheKeyOk bool
	cacheTreeData, cacheTreeOk := app.App().Cache().Get(CacheCardFileTreeDataKey(fileId))
	cacheKeyData, cacheKeyOk := app.App().Cache().Get(CacheCardFileAccountMapKey(fileId))
	cacheClassifyList, cacheClassifyOk := app.App().Cache().Get(CacheCardClassifyListKey(fileId))
	if cacheTreeOk && cacheKeyOk && cacheClassifyOk {
		treeData = cacheTreeData.([]res.TreeNode)
		keyMaps = cacheKeyData.(map[int64]res.CardInfo)
		classifyList = cacheClassifyList.([]res.BoxInfo)
		app.App().Log().Services().Println("从缓存中加载卡片文件数据")
		return treeData, keyMaps, classifyList
	}

	// 读取 Excel 文件
	excelFile, err := excelize.OpenFile(file.FilePath)
	if err != nil {
		log.Fatal(err)
		return nil, nil, nil
	}
	// 读取 Excel 内容
	rows, err := excelFile.GetRows("Sheet1")
	if err != nil {
		log.Fatal(err)
		return nil, nil, nil
	}
	boxes, keyMaps := classifyCard(rows)
	treeData = convertBoxesToTree(boxes)
	// cache
	app.App().Cache().Set(CacheCardFileTreeDataKey(fileId), treeData, 0)
	app.App().Cache().Set(CacheCardFileAccountMapKey(fileId), keyMaps, 0)
	app.App().Cache().Set(CacheCardClassifyListKey(fileId), boxes, 0)
	return treeData, keyMaps, boxes
}

// classifyCard 分类卡片
func classifyCard(rows [][]string) ([]res.BoxInfo, map[int64]res.CardInfo) {
	var boxes []res.BoxInfo
	var currentBox res.BoxInfo
	var currentStage res.StageInfo
	var prevAccount int64
	var currentBoxCardCount int64
	// 初始化第一个盒子
	currentBox = res.BoxInfo{
		Number: 1,
		Count:  0,
		List:   make([]res.StageInfo, 0),
	}
	allCards := make(map[int64]res.CardInfo)
	for i := 1; i < len(rows); i++ { // 从1开始，跳过表头
		row := rows[i]
		// 解析每一行数据
		uqKey := cast.ToInt64(row[0])
		account := cast.ToInt64(row[1])
		password := cast.ToInt64(row[2])

		cardInfo := res.CardInfo{
			UqKey:    uqKey,
			Account:  account,
			Password: password,
		}
		allCards[account] = cardInfo
		if i == 1 { // 初始化第一个阶段
			currentStage = res.StageInfo{
				StartNum: account,
				Count:    1, // 初始化阶段的卡片计数
				List:     []res.CardInfo{cardInfo},
			}
			currentBoxCardCount++ // 计算卡片总数
		} else {
			// 检查是否存在断层（账户号不连续）或当前盒子中的卡片已满
			if account != prevAccount+1 || currentBoxCardCount >= 200 {
				// 完成当前阶段
				currentStage.EndNum = prevAccount
				currentStage.Desc = fmt.Sprintf("Stage %d: %d - %d", len(currentBox.List)+1, currentStage.StartNum, currentStage.EndNum)
				// 将完成的阶段添加到 Box 中
				currentBox.List = append(currentBox.List, currentStage)

				// 检查当前 Box 是否已经满 200 张卡片
				if currentBoxCardCount >= 200 {
					currentBox.Count = currentBoxCardCount
					boxes = append(boxes, currentBox)
					// 初始化一个新的 BoxInfo
					currentBox = res.BoxInfo{
						Number: currentBox.Number + 1,
						Count:  0,
						List:   make([]res.StageInfo, 0),
					}
					currentBoxCardCount = 0
				}

				// 初始化一个新的 StageInfo
				currentStage = res.StageInfo{
					StartNum: account,
					Count:    1, // 初始化阶段的卡片计数
					List:     []res.CardInfo{cardInfo},
				}
				currentBoxCardCount++
			} else {
				// 如果连续，继续添加到当前阶段
				currentStage.List = append(currentStage.List, cardInfo)
				currentStage.Count++ // 增加阶段的卡片计数
				currentBoxCardCount++
			}
		}
		// 更新上一个账户号
		prevAccount = account
	}

	// 处理最后一个阶段
	if len(currentStage.List) > 0 {
		currentStage.EndNum = prevAccount
		currentStage.Desc = fmt.Sprintf("Stage %d: %d - %d", len(currentBox.List)+1, currentStage.StartNum, currentStage.EndNum)
		currentBox.List = append(currentBox.List, currentStage)
		currentBoxCardCount += int64(len(currentStage.List))
	}

	// 如果当前 Box 中有剩余的阶段，将其添加到结果中
	if currentBoxCardCount > 0 {
		currentBox.Count = currentBoxCardCount
		boxes = append(boxes, currentBox)
	}
	return boxes, allCards
}

// 递归函数，组装树形结构
func convertBoxInfoToTree(boxInfo res.BoxInfo, idCounter *int) res.TreeNode {
	oldId := *idCounter
	// 创建每个 BoxInfo 的根节点
	root := res.TreeNode{
		Id:       *idCounter, // 使用递增的 idCounter 作为 Id
		ParentId: 0,
		Name:     fmt.Sprintf("Box %d", boxInfo.Number),
		Children: []res.TreeNode{},
	}
	*idCounter++ // 更新 idCounter

	// 递归处理每个 StageInfo
	for _, stage := range boxInfo.List {
		stageNode := res.TreeNode{
			Id:          int(stage.StartNum), // 使用递增的 idCounter 作为 Id
			ParentId:    oldId,
			Name:        fmt.Sprintf(" %d ~ %d", stage.StartNum, stage.EndNum),
			Description: fmt.Sprintf("%d cards", stage.Count),
			Children:    []res.TreeNode{},
		}
		root.Children = append(root.Children, stageNode)
	}
	return root
}

// 将多个 BoxInfo 组装成树形结构列表
func convertBoxesToTree(boxes []res.BoxInfo) []res.TreeNode {
	var treeList []res.TreeNode
	idCounter := 1

	for _, box := range boxes {
		treeNode := convertBoxInfoToTree(box, &idCounter)
		treeList = append(treeList, treeNode)
	}
	return treeList
}

// Check if a file exists
func fileExists(filename string) bool {
	info, err := os.Stat(filename)
	if os.IsNotExist(err) {
		return false
	}
	return !info.IsDir()
}
